Python3.12 のスタンドアロン Lambda 関数を作成しつつ、SAM CLIを学んでみた
はじめに
こんにちは、アノテーションのなかたです。
今回は、Python3.12 のスタンドアロン Lambda 関数を作成しつつ、SAM CLIを学んでみました。
1. テンプレートからプロジェクトを作成する
Standalone function
クイックテンプレートでは Pythonランタイム がサポートされていない
sam init 時に、 AWS Quick Start application template
に Standalone function
という、それらしいテンプレートがあったので選択したのですが、dotnet と nodejs しか表示されませんでした。
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Data processing
3 - Hello World Example with Powertools for AWS Lambda
4 - Multi-step workflow
5 - Scheduled task
6 - Standalone function
7 - Serverless API
8 - Infrastructure event management
9 - Lambda Response Streaming
10 - Serverless Connector Hello World Example
11 - Multi-step workflow with Connectors
12 - GraphQLApi Hello World Example
13 - Full Stack
14 - Lambda EFS example
15 - DynamoDB Example
16 - Machine Learning
Template: 6
Which runtime would you like to use?
1 - dotnet8
2 - dotnet6
3 - nodejs20.x
4 - nodejs18.x
5 - nodejs16.x
Hello World Example
から API Gateway を削除して対応
前項により、Hello World Example テンプレート から API Gateway を手動削除することで構築してみました。
sam init
を実行します。
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Data processing
3 - Hello World Example with Powertools for AWS Lambda
4 - Multi-step workflow
5 - Scheduled task
6 - Standalone function
7 - Serverless API
8 - Infrastructure event management
9 - Lambda Response Streaming
10 - Serverless Connector Hello World Example
11 - Multi-step workflow with Connectors
12 - GraphQLApi Hello World Example
13 - Full Stack
14 - Lambda EFS example
15 - DynamoDB Example
16 - Machine Learning
Template: 1
Use the most popular runtime and package type? (python3.12 and zip) [y/N]: y
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: N
Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]: y
Structured Logging in JSON format might incur an additional cost. View https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-pricing for more details
Project name [sam-app]: sam-standalone-python
Use the most popular runtime and package type? (python3.12 and zip)
このテンプレートでは、デフォルトで python3.12 が選択されるのでランタイムを変更する必要はありませんでした。
コマンドの実行結果として、以下のようにディレクトリが作成されます。
% tree
.
├── README.md
├── __init__.py
├── events
│ └── event.json
├── hello_world
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── samconfig.toml
├── template.yaml
└── tests
├── __init__.py
├── integration
│ ├── __init__.py
│ └── test_api_gateway.py
├── requirements.txt
└── unit
├── __init__.py
└── test_handler.py
template.yml
からAPI Gateway 部分を削除
AWS::Serverless::Function の Events が API Gateway に該当します。
Events と Eventsに依存する Outputs 部分を削除します。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
sam-standalone-python
Sample SAM Template for sam-standalone-python
Globals:
Function:
Timeout: 3
LoggingConfig:
LogFormat: JSON
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.12
Architectures:
- x86_64
- Events:
- HelloWorld:
- Type: Api
- Properties:
- Path: /hello
- Method: get
Outputs:
- HelloWorldApi:
- Description: API Gateway endpoint URL for Prod stage for Hello World function
- Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: Hello World Lambda Function ARN
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: Implicit IAM Role created for Hello World function
Value: !GetAtt HelloWorldFunctionRole.Arn
また、デフォルトでは requirements.txt
に requests ライブラリが入っています。
requests
今回は requests ライブラリを使う予定はないので、こちらは削除します。
後に外部ライブラリを用いるため、ファイル自体は残しておきます。
- requests
requestsライブラリを残した場合
Lambda関数にアップロードされるソースコードはこちらのようになります。
requests ライブラリや依存するライブラリがアップロードされてしまっています。
※Pythonスクリプトは少しだけ変更を加えています
2. ビルドしてデプロイする
sam validate
まず、SAMテンプレートとして構文エラーが存在するか確認します。
% sam validate
/Users/dummy/Documents/Dev/sam_learn/sam-standalone-python/template.yaml is a valid SAM Template
sam build
template.yml
から CloudFormation ファイルを作成したり、コードのライブラリの依存関係を解決するコマンドです。
sam build
% sam build
Starting Build use cache
Manifest file is changed (new hash: 3298f13049d19cffaa37ca931dd4d421) or dependency folder (.aws-sam/deps/0feab3f2-3197-4309-8842-6b7be69123cb) is
missing for (HelloWorldFunction), downloading dependencies and copying/building source
Building codeuri: /Users/dummy/Documents/Dev/sam_learn/sam-standalone-python/hello_world runtime: python3.12 architecture: x86_64
functions: HelloWorldFunction
Running PythonPipBuilder:CleanUp
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
dummy sam-standalone-python % sam local invoke
Invoking app.lambda_handler (python3.12)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.
Mounting /Users/dummy/Documents/Dev/sam_learn/sam-standalone-python/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside
runtime container
START RequestId: e0560354-063f-4fda-88cd-7da02b0e815f Version: $LATEST
event = {}
END RequestId: 23bfb985-fa17-4310-b17d-a3bb548929b6
REPORT RequestId: 23bfb985-fa17-4310-b17d-a3bb548929b6 Init Duration: 0.13 ms Duration: 117.81 ms Billed Duration: 118 ms Memory Size: 128 MBMax Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
dummy sam-standalone-python % sam deploy
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-dummy
A different default S3 bucket can be set in samconfig.toml
Or by specifying --s3-bucket explicitly.
Uploading to dummy 572845 / 572845 (100.00%)
Deploying with following values
===============================
Stack name : sam-standalone-python
Region : ap-northeast-1
Confirm changeset : True
Disable rollback : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-dummy
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to 5eb472a6bdc5355e14695bb4e76908e5.template 909 / 909 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
---------------------------------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
---------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:dummy:changeSet/samcli-deploy1730994357/dummy
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2024-11-08 00:46:06 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::Stack sam-standalone-python User Initiated
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated
CREATE_IN_PROGRESS - AWS::Lambda::Function HelloWorldFunction Eventual consistency check
CONFIGURATION_COMPLETE initiated
CREATE_IN_PROGRESS - AWS::CloudFormation::Stack sam-standalone-python Eventual consistency check
CONFIGURATION_COMPLETE
sam deploy
ビルドしたものをAWSにデプロイします。
3. マネジメントコンソールから作成されたリソースを確認する
正常にリソースが作成されていることが CloudFormation からも確認できました。
LambdaのIAMロールはデフォルトで AWSLambdaBasicExecutionRole
ロールが指定されるようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Lambda関数は以下のようになっていました。
※Pythonスクリプトは少しだけ変更を加えています
デプロイが正常に行われたことを確認できたため、gitでコード管理する場合は、この時点でコミットしておくと良いと思います。
4. boto3 ライブラリを追加してみる
boto3 ライブラリ群をビルドする
requirements.txt
に boto3
と加えるだけでライブラリを追加できます。
+ boto3
sam build
します。
ビルドされたディレクトリ見ると、boto3 の実行に必要なライブラリ群も追加されたことがわかります。
% tree .aws-sam/build/HelloWorldFunction/ -L 1
.aws-sam/build/HelloWorldFunction/
├── __init__.py
├── app.py
+ ├── boto3
+ ├── boto3-1.35.55.dist-info
+ ├── botocore
+ ├── botocore-1.35.55.dist-info
+ ├── dateutil
+ ├── jmespath
+ ├── jmespath-1.0.1.data
+ ├── jmespath-1.0.1.dist-info
+ ├── python_dateutil-2.9.0.post0.dist-info
├── requirements.txt
+ ├── s3transfer
+ ├── s3transfer-0.10.3.dist-info
+ ├── six-1.16.0.dist-info
+ ├── six.py
+ ├── urllib3
+ └── urllib3-2.2.3.dist-info
15 directories, 4 files
5. ローカルでコードをテスト実行する
新しいライブラリを追加したので、正常に実行されるかどうかテストしたいところです。
SAM CLI では sam local invoke
という、ローカルで Lambda 関数のテストができる便利なコマンドが用意されています。
Lambdaのコンテナ環境を起動し、ローカルで擬似的にリクエストをテストします。
こちらを実行することで、テストしてみようと思います。
また、通信を伴う処理となると実行に時間がかかるため、タイムアウト値を上げておきます。
...
Globals:
Function:
- Timeout: 3
+ Timeout: 15
...
変更を反映するため、sam build
しておきます。
% sam build
Starting Build use cache
Manifest is not changed for (HelloWorldFunction), running incremental build
Building codeuri: /Users/dummy/Documents/Dev/sam_learn/sam-standalone-python/hello_world runtime: python3.12 architecture: x86_64
functions: HelloWorldFunction
Running PythonPipBuilder:CopySource
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
sam local invoke
sam local invoke
を実行します。
% sam local invoke
Invoking app.lambda_handler (python3.12)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.
Mounting /Users/dummy/Documents/Dev/sam_learn/sam-standalone-python/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside
runtime container
START RequestId: 6ddb8a7e-c12d-4a50-bb06-94c857651d42 Version: $LATEST
{"timestamp": "2024-11-07T16:57:26Z", "level": "INFO", "message": "Found credentials in environment variables.", "logger": "botocore.credentials", "requestId": "eb787c0a-a695-4a7e-ac7f-46b0bbce1ac4"}
Tokyo Region Instance IDs: ['i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId', 'i-instanceId']
END RequestId: eb787c0a-a695-4a7e-ac7f-46b0bbce1ac4
REPORT RequestId: eb787c0a-a695-4a7e-ac7f-46b0bbce1ac4 Init Duration: 0.07 ms Duration: 7142.18 ms Billed Duration: 7143 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"Successfully retrieved instance IDs\", \"instanceIds\": [\"i-instanceId\", \"i-instanceId\", \"i-instanceId", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\", \"i-instanceId\"]}"}
boto3 によるEC2インスタンスの取得が実行できたことがわかります。
使用したPythonスクリプト
Claude 3.5 Sonnet v1 に書いてもらいました。
import json
import boto3
def lambda_handler(event, context):
# 東京リージョンのEC2クライアントを作成
ec2 = boto3.client('ec2', region_name='ap-northeast-1')
# 東京リージョンのすべてのEC2インスタンス情報を取得
instances = ec2.describe_instances()
# インスタンスIDのリストを作成
instance_ids = []
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
instance_ids.append(instance['InstanceId'])
# インスタンスIDを表示
print("Tokyo Region Instance IDs:", instance_ids)
# Lambda関数の戻り値を作成
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Successfully retrieved instance IDs',
'instanceIds': instance_ids
})
}
再度デプロイする
再度デプロイを行います。
% sam deploy
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxx
A different default S3 bucket can be set in samconfig.toml
Or by specifying --s3-bucket explicitly.
Uploading to 99fdc22fced05169c7a7d541f467bd72 13323456 / 13323456 (100.00%)
Deploying with following values
===============================
Stack name : sam-standalone-python
Region : ap-northeast-1
Confirm changeset : True
Disable rollback : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxx
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to cb1cfad616af3e0ee8b8d7f3263e279c.template 910 / 910 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
---------------------------------------------------------------------------------------------------------------------------------------------
* Modify HelloWorldFunction AWS::Lambda::Function False
---------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxx:changeSet/samcli-deployxxxxxxxxxx/a9d596ce-9dc4-4d09-8efe-fa6b51e75b85
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2024-11-08 02:31:59 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS AWS::CloudFormation::Stack sam-standalone-python User Initiated
UPDATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
UPDATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
UPDATE_COMPLETE_CLEANUP_IN_PROGRE AWS::CloudFormation::Stack sam-standalone-python -
SS
UPDATE_COMPLETE AWS::CloudFormation::Stack sam-standalone-python -
---------------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
------------------------------------------------------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::xxxxxxxxxx:role/sam-standalone-python-HelloWorldFunctionRole-iHwC7YZ8YQ19
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:xxxxxxxxxx:function:sam-standalone-python-HelloWorldFunction-Ztao7M9Kyybg
------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-standalone-python in ap-northeast-1
無事にデプロイが完了しました。
おわりに
SAM の体験として、構成をyamlファイルとして残しておけるところやローカルでテストが行える点が良かったです。
template.yml
に関しては、CloudFormation の理解を深めることでより強力に活かせそうだなと感じました。
参考
アノテーション株式会社について
アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。